#ifndef BARKGEN_H
#define BARKGEN_H
//#define BARK_WIDTH 128
//#define BARK_HEIGHT 256

#define BARK_WIDTH 128
#define BARK_HEIGHT 256

#define STRESS_CONSTANT 1

//#define N_LENTICELS 5
//#define M_SPLITS 0

#define N_LENTICELS 0
#define M_SPLITS 3

#define SPLIT_PROB .5
#define SPLIT_STRESS_THRESHOLD .25
#define LENTICEL_EXPANSION_SPEED 1
#define STARTING_THICKNESS 3
#define SPLIT_LOW 1
#define SPLIT_HIGH 8
#define INCREMENT_THICKNESS 1

#include "common.h"
#include "GL/gl.h"
#include <stdlib.h>
#include <stdio.h>
enum BARK_UNIT_TYPE{COMMON, LENTICEL, SPLIT};
enum SPLIT_END{HEAD, TAIL, NEITHER}; //TAIL always goes down, HEAD always goes up, if NEITHER, no direction,
//active flag also doesn't matter for NEITHERS, just set it to false
enum CUR_DIRECTION{NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, NORTHWEST};

const float stress_template[8] = {.2, .1, .1, .1, .2, .1, .1, .1};
const float north_template[8] = {.4, .15, .15, 0, 0, 0, .15, .15};
const float northeast_template[8] = {.15, .4, .15, .15, 0, 0, 0, .15};
const float east_template[8] = {.15, .15, .4, .15, .15, 0, 0, 0};
const float southeast_template[8] = { 0, .15, .15, .4, .15, .15, 0, 0};
const float south_template[8] = {0, 0, .15, .15, .4, .15, .15, 0};
const float southwest_template[8] = {0, 0, 0, .15, .15, .4, .15, .15};
const float west_template[8] = {.15, 0, 0, 0, .15, .15, .4, .15};
const float northwest_template[8] = {.15, .15, 0, 0, 0, .15, .15, .4};
const float lenticel_template[9] = {.15,.15,.15,1.0,0,1.0,.15,.15,.15};
struct BarkUnit{
    float3 normal;
    float thickness;
    BARK_UNIT_TYPE b_type;
    float stress;
    //for split usage
    bool active;
    SPLIT_END terminal;
    CUR_DIRECTION path;
    int age;
    bool expand;
    int split_id;
    int widen_rate;
};

struct BarkStruct{
        GLuint barkID;
        GLuint normalID;
        int age;
        BarkUnit barkInfo[BARK_WIDTH*BARK_HEIGHT];
};

class BarkGen
{
public:
    int cur_split_id;
    float3 lenticelColor;
    float3 splitColor;
    float3 commonColor;
    const float stressConstant;
    BarkGen();
    void initBark(BarkStruct &bark);
    void generateSplits(BarkStruct &bark);
    void updateLenticels(BarkUnit * b_unit,BarkUnit *b_info, int i, int j);
    int coordToIndex(int x, int y);
    void perlinNoiseGen(BarkUnit *b_info);
    void ageBark(BarkStruct &bark);
    void barkToTexture(BarkStruct &bark);
    void repopulateNormals(BarkStruct &bark);
    bool isNearStop(BarkUnit * b_info, int i, int j);
    int coordToIndexWrap(int i, int j);
    CUR_DIRECTION extendSplit(BarkStruct &bark, BarkUnit *curUnit, int &curRow, int &curCol);
    void getSurroundingStress(BarkUnit * info, float *stress, int i, int j);
    void getProbabilities(float * probs, float * stress, const float * stresst, const float * directiont);
    void drawNormals(BarkStruct &bark);
    int calculateWidenRate(int i);
};

#endif // BARKGEN_H
